package org.phalanx.server.game;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;

import org.phalanx.map.MapCoordinates;
import org.phalanx.messenging.MessageFeedListener;
import org.phalanx.server.PhalanxServer;
import org.phalanx.server.ServerCache.CacheManager;

public class PhalanxGameTurnTimer extends Thread {
	private Long nextTurnTime = 0L;
	private Long pausedDelta = null;
	private ArrayList<Integer> turnList;
	private Integer gameId;
	private boolean isPaused;

	public PhalanxGameTurnTimer(Integer gameId){
		turnList = new ArrayList<Integer>();
		this.gameId = gameId;
		setPaused(true);
	}

	public void run(){
		CacheManager cacheMgr = PhalanxServer.getServerInstance().getCacheManager();
		PhalanxGameSettings settings = (PhalanxGameSettings)cacheMgr.getElement("GameListCache", gameId);

		if (settings != null && !settings.getTurnMode().equals(PhalanxGameSettings.PURE_TURN_MODE)){
			Integer turnLength = settings.getTurnTime() * 1000;
			nextTurnTime = new Date().getTime() + turnLength;

			while(!isPaused){
				try {
					Thread.sleep(1000);

					if (new Date().getTime() >= nextTurnTime){
						// Process turn
						PhalanxBattleRPGEngine rpgEngine = (PhalanxBattleRPGEngine)cacheMgr.getElement("GameEngineCache", gameId);

						GameMoveQueue gQueue = (GameMoveQueue)cacheMgr.getElement("PlayerMoveCache", gameId);
						// Grab game Queue from memory cache as it hasn't been written to DB yet

						if (gQueue != null){
							cacheMgr.setElement("PlayerMoveCache", gameId, gQueue); // Write to DB before proceeding
						}

						if (rpgEngine != null){
							rpgEngine.calculateGameState();
							//							settings.setCurrentTurn(settings.getCurrentTurn()+1);
							nextTurnTime = new Date().getTime() + turnLength;
							turnList.clear();
						}
						sendUsersNewGameState();
					}
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	public Long getTimeUntilNextTurn(){
		return nextTurnTime;
	}

	public void setPaused(boolean paused){
		isPaused = paused;
		if (!isPaused){
			if (pausedDelta != null){
				nextTurnTime = pausedDelta + new Date().getTime();
			}
			start();
		} else {
			if (nextTurnTime == 0){
				pausedDelta = 0L;
			} else {
				pausedDelta = nextTurnTime - new Date().getTime();
			}
		}
	}

	public void setTurnFinished(Integer uId){
		CacheManager cacheMgr = PhalanxServer.getServerInstance().getCacheManager();
		GameMembers gMember = (GameMembers)cacheMgr.getElement("UserGameCache", uId);
		PhalanxGameSettings settings = (PhalanxGameSettings)cacheMgr.getElement("GameListCache", gameId);

		if (!turnList.contains(uId) && gMember.hasGameId(gameId)){
			turnList.add(uId);

			if (turnList.size() == settings.getNumberOfPlayers()){
				GameMoveQueue gQueue = (GameMoveQueue)cacheMgr.getElement("PlayerMoveCache", gameId);
				// Grab game Queue from memory cache as it hasn't been written to DB yet

				if (gQueue != null){
					cacheMgr.setElement("PlayerMoveCache", gameId, gQueue); // Write to DB before proceeding
				}
				PhalanxBattleRPGEngine rpgEngine = (PhalanxBattleRPGEngine)cacheMgr.getElement("GameEngineCache", gameId);

				if (rpgEngine != null){
					rpgEngine.calculateGameState();
					//					settings.setCurrentTurn(settings.getCurrentTurn()+1);
					turnList.clear();
					sendUsersNewGameState();
				}
			}
		}
	}

	public ArrayList<Integer> getTurnCompletedUsers(){
		return turnList;
	}

	public boolean getIsPaused(){
		return isPaused;
	}

	public void sendUsersNewGameState(){
		CacheManager cacheMgr = PhalanxServer.getServerInstance().getCacheManager();
		MessageFeedListener gameFeed = (MessageFeedListener)cacheMgr.getElement("GameFeedCache", gameId);

		if (gameFeed != null){
			Iterator<Integer> i = gameFeed.getUsers().iterator();

			while (i.hasNext()){
				Integer oneUserId = i.next();
				sendGameFeedToUser(oneUserId);
			}
		}
	}

	public void sendGameFeedToUser(Integer uId){
		CacheManager cacheMgr = PhalanxServer.getServerInstance().getCacheManager();
		PhalanxGameSettings settings = (PhalanxGameSettings)cacheMgr.getElement("GameListCache", gameId);
		PhalanxBattleRPGEngine rpgEngine = (PhalanxBattleRPGEngine)cacheMgr.getElement("GameEngineCache", gameId);
		MessageFeedListener gameFeed = (MessageFeedListener)cacheMgr.getElement("GameFeedCache", gameId);

		if (gameFeed != null){
			Iterator<Integer> i = gameFeed.getUsers().iterator();
			Integer turnId = settings.getCurrentTurn();

			Integer oneUserId = uId;

			ArrayList<PhalanxUnitState> visibleUnits = rpgEngine.getVisibleUnits(oneUserId, turnId);
			ArrayList<MapCoordinates> fieldOfVision = rpgEngine.getTotalFieldOfVision(oneUserId, turnId);

			PhalanxGameStateMessage pStateMsg = new PhalanxGameStateMessage();
			pStateMsg.setFieldOfVision(fieldOfVision);
			pStateMsg.setGameId(gameId);
			pStateMsg.setTurn(turnId);
			pStateMsg.setUserGameState(visibleUnits);
			pStateMsg.setUserId(oneUserId);

			if (settings.getTurnMode() > PhalanxGameSettings.PURE_TURN_MODE){
				pStateMsg.setTimeUntilNextTurn(nextTurnTime);
			}

			gameFeed.sendGameDataToFeed(pStateMsg, oneUserId);
		}
	}
}
